<script>
// function fn() {}
// fn = () => {}

// var user = (username, userId) => {username, userId}


const user = {
  fullname: '乔布斯',
  sayHi(p) {
    console.log(this)
    console.log(`${this.fullname} 对 ${p} 说：Hi`)
  }
}
user.sayHi('侯广杰')

const {sayHi} = user
sayHi('侯广杰')

const user2 = {
  fullname: '比尔盖茨'
}
user2.sayHi = sayHi
user2.sayHi('侯广杰')

const clazz = {
  name: '2107a',
  users: [{
    fullname: '马云',
    sayHi: sayHi
  }]
}

clazz.users[0].sayHi('aaa')

let user4 = {fullname: '张三'}
sayHi.apply(user4, ['某某'])
sayHi.call(user4, '某某2')
// user4.sayHi = sayHi
// user4.sayHi('某某')

user.sayHi.apply(user4, ['某某3'])

/*
function 声明的函数 this是跟随调用的上下文变化的（this是不固定的）

```
obj1.obj2.fn()  // this是obj1.obj2
// fn的this是.前面的所有对象
```

```
fn.call(obj)/fn.apply(obj) // this是obj
// 如果用apply/call去指定fn的this，
//  fn会用指定的参数作为自己的this
```

````
fn() // this是window
// 如果调用方法没有上下文，也没有用apply/call，
//  fn里的this会使用全局里顶级变量当成this（非严格模式）
```

```
const fn2 = fn.bind(obj)
// fn.bind(obj) 返回一个新的function
// fn2里this是固定的，不变的，
fn2() // this是obj
fn2.call(obj2) // this还是obj
user.fn2() // this还是obj
const fn3 = fn2.bind(obj2) // fn3里的this仍然是obj
```
*/

var name = '盖茨'

var person = {
  name: '乔布斯',
  sayHi: function () {
    // 箭头函数它会自动绑定当前定义箭头函数环境内部的this值
    console.log(this)
    // const fn =  (function() {
    //   console.log('Hi, ' + this.name)
    // }).bind(this)
    // setTimeout(fn)
    setTimeout(() => {
      console.log('Hi, ' + this.name)
    })
  },
}
person.sayHi() // Hi, 盖茨

person.sayHi.call({name: '马云'})

var person4 = {
  name: '乔布斯',
  sayHi: () => {
    console.log(this.name)
  },
}
person4.sayHi()


function fn4() {
  console.log(this)
  let obj = {
    a: 1,
    b: () => {console.log(this)}
  }
  obj.a = 1
  obj.b = () => console.log(this)
}
</script>